package tech.aistar.util;

import java.util.Arrays;

/**
 * 本类用来演示: 自定义的数组工具类
 *
 * @author: success
 * @date: 2021/3/8 3:59 下午
 */
public class ArrayUtil {
    public static void main(String[] args) {
        int[] arr = {1,2,2,2,1,3,3};
        //System.out.println(max(arr));
        //int[] temps = delByIndex(arr,2);

        //int[] temp = delByIndex2(arr,2);
//        for (int i = 0; i < temp.length; i++) {
//            System.out.println(temp[i]);
//        }

//        for (int i = 0; i < arr.length; i++) {
//            System.out.println(arr[i]);
//        }

//        int[] temps = delByTarget(arr,2);
//        for (int i = 0; i < temps.length; i++) {
//            System.out.println(temps[i]);
//        }

        int[] temps = delRepeats3(arr);
        for (int temp : temps) {
            System.out.println(temp);
        }
    }

    /**
     * 找出数组中最大的数字 - 不要考虑最大的数字有多个
     * @param arr
     * @return
     */
    public static int max(int[] arr){
        if(null== arr || arr.length==0){
            return -1;//错误的标志
        }
        //定义一个变量,用来保存是最大的数字
        int max=arr[0];//假设数组中的第一个元素是最大的

        for (int i = 1; i < arr.length; i++) {
            if(arr[i]>max){
                max = arr[i];
            }
        }
        return max;
    }

    /**
     * 根据下标删除方法2
     * @param arr
     * @param pos
     * @return
     */
    public static int[] delByIndex2(int[] arr,int pos){
        if(null== arr || arr.length==0 || pos<0 || pos>arr.length-1){
            return new int[]{-1};//错误的标志
        }
        //要先将arr中的所有的数据全部放到另外一个数组中,然后对这个新的数组进行覆盖操作
        //不要动arr

        //思路:后面的覆盖前面的.
        for (int i = pos; i < arr.length-1; i++) {
            arr[i] = arr[i+1];
        }

        //数组的拷贝操作
        int[] temp = new int[arr.length-1];
        for (int i = 0; i < arr.length-1; i++) {
            temp[i] = arr[i];
        }
        return temp;
    }

    /**
     * 从指定数组arr中,删除指定下标pos处的值
     * int[] temp = new int[arr.length-1];
     * @param arr
     * @param pos 下标
     * @return
     */
    public static int[] delByIndex(int[] arr,int pos){
        if(null== arr || arr.length==0 || pos<0 || pos>arr.length-1){
            return new int[]{-1};//错误的标志
        }
        //数组的大小一旦固定了,就不能够改变
        //所以本质上是不会对原来的数组进行直接的删除操作
        //效果是:准备一个新的数组,这个新的数组中最终不包含pos处对应的arr数组中的值

        //1. 确定新的数组 - 因为下标是唯一的
        int[] temp = new int[arr.length-1];

        //2. 定义一个变量
        int index = 0;

        //3. 存放
        for (int i = 0; i < arr.length; i++) {
            //将不是pos处的值全部拷贝一份给temp
            if(i!=pos) {
                //数组在内存你中是一块连续的空间,数组的下标一定具有连续性
                temp[index++] = arr[i];
            }
        }

        return temp;
    }

    /**
     * 从指定的数组arr中删除所有的target元素.如果target元素不存在,则返回原来的arr
     * @param arr
     * @param target
     * @return
     */
    public static int[] delByTarget(int[] arr,int target){
        if(null== arr || arr.length==0){
            return new int[]{-1};//错误的标志
        }
        //确定target的个数
        //定义一个变量 - 计数器
        int count = 0;
        for (int i = 0; i < arr.length; i++) {
            if(arr[i]==target){
                count++;
            }
        }
        if(count==0){
            //target不存在
            return new int[]{-1};
        }

        //target存在..
        //确定新的数组的长度
        int[] temp = new int[arr.length - count];

        //定义一个下标计数器
        int index = 0;

        // 1 2x 3 4 2x 5  2x 6

        // 1 3  0 0 0

        for (int i = 0; i < arr.length; i++) {
            if(arr[i]!=target){
                temp[index++] = arr[i];
            }
        }

        return temp;
    }

    /**
     * 笔试题:
     * 删除数组中重复的数据,保留1个 - 数组去重
     * [1,2,3,2,1,2,3,4,2] -> [1,2,3,4]
     *
     * 思路一:
     * []
     * [1,2,3,4,0,0,0,0,0]
     *
     * @param arr
     * @return
     */
    public static int[] delRepeatElements(int[] arr){
        if(arr == null || arr.length==0){
            return new int[]{-1};
        }
        //定义新的数组
        int[] temp = new int[arr.length];
        //定义一个下标计数器
        int index = 0;

        //永远是先将arr[0]的元素放入到temp中
        do{
            temp[index++] = arr[0];
            //立即到arr指向的那个数组"删除"所有的arr[0]
            arr = delByTarget(arr,arr[0]);
            //判断循环退出的条件
            if(arr.length == 0)
                break;
        }while(true);

        //数组的拷贝 - 手动方式
//        int[] copys = new int[index];
//
//        for (int i = 0; i < index; i++) {
//            copys[i] = temp[i];
//        }

        //return copys;

        temp = Arrays.copyOf(temp,index);
        return temp;
    }

    /**
     * 数组去重方式2
     * {1,2,4,5}
     * 思路:将每个arr[i]和它后面所有位置的值进行比较,
     * 如果一样,则调用根据下标进行删除
     *
     * @param arr
     * @return
     */
    public static int[] delRepeats2(int[] arr){
        if(arr == null || arr.length==0){
            return new int[]{-1};
        }
        for (int i = 0; i < arr.length; i++) {
            for (int j = i+1; j < arr.length; j++) {
                if(arr[i] == arr[j]){
                    //根据下标进行删除操作
                    arr = delByIndex(arr,j);
                    j--;//防止连续的数字在一起的时候,漏删
                    //delByIndex2(arr,j);
                    //{1,2,2,1,3,3} -> {1,2,2,3}

                }
            }
        }
        return arr;
    }

    /**
     * T T F T T T T T T T
     * 1 2 3 4 5 6 7 8 9 10 - 依次报数1,2,3
     * 报到3的小孩依次出列,输出出列的顺序
     *
     * 3 6 9 2
     *
     * 数组去重方式3 -
     * {1,2,2,1,3,3}
     * {T,T,F,F,T,F}
     * @param arr
     * @return
     */
    public static int[] delRepeats3(int[] arr){
        if(arr == null || arr.length==0){
            return new int[]{-1};
        }
        boolean[] flags = new boolean[arr.length];

        //全部设置成true
        for (int i = 0; i < flags.length; i++) {
            flags[i] = true;
        }

        //拿着arr[i]和它后面所有位置上的值进行一一比较
        //如果某个位置j和arr[i]一样,那么就设置flags[j] = false;
        for (int i = 0; i < arr.length; i++) {
            for (int j = i+1; j < arr.length; j++) {
                if(arr[i] ==  arr[j]){
                    flags[j] = false;
                }
            }
        }

        //定义一个计数器
        int count = 0;
        for (int i = 0; i < flags.length; i++) {
            if(flags[i])
                count++;//统计true的个数 - 去完重之后的个数
        }

        int[] temp =  new int[count];
        //定义一个下标计数器
        int pos = 0;
        for (int i = 0; i < arr.length; i++) {
            if(flags[i]) {
                temp[pos++] = arr[i];
            }
        }
        return temp;
    }

    /**
     * 在数组arr的指定pos处插入单个target值
     * @param arr
     * @param pos
     * @param target
     * @return
     */
    public static int[] insertOneElement(int[] arr,int pos,int target){
        return null;
    }



//    拓展题目 - 百度的面试题
    public static int[][] countAndSort(){
        //比如数组 - 长度是15个,里面的数据是1-5之间的随机整数
        //int[] arr = {1,2,1,2,3,4,5,6,1,2,3,5,...};
        //1. 统计每个数字出现的次数
        //2. 根据出现的次数进行降序排列
        return null;
    }
}
